﻿using UnityEngine;
using System.Collections.Generic;
using DG.Tweening;
using System;
using System.Linq;
using LuaInterface;

namespace YanhuaMMO {
    public class SoundManager : Manager {
        public static SoundManager Instance = null;
        private readonly Dictionary<string, AudioSource> _dicAudio = new Dictionary<string, AudioSource>();
        private AudioSource _bgAudio;
        private string _musicHistory = "";
        private float _soundVolume = 0.7f;
        private float _musicVolume = 0.7f;
        private float _cvVolume = 0.7f;
        private float _maxSoundVolume = 100;
        private float _maxMusicVolume = 100;
        private float _maxCvVolume = 100;
        private bool _setVolumeFinish = false;
		private bool _enableSound;//音效是否可播放
        void Start()
        {
            Instance = this;
            if (_bgAudio == null)
                _bgAudio = gameObject.AddComponent<AudioSource>();
            if (PlayerPrefs.HasKey("SoundVolume"))
            {
                _soundVolume = float.Parse(PlayerPrefs.GetString("SoundVolume"));
            }
            else
            {
                PlayerPrefs.SetString("SoundVolume", "0.7");
            }
            if (PlayerPrefs.HasKey("MusicVolume"))
            {
                _musicVolume = float.Parse(PlayerPrefs.GetString("MusicVolume"));
            }
            else
            {
                PlayerPrefs.SetString("MusicVolume", "0.7");
            }
            if (PlayerPrefs.HasKey("CVVolume"))
            {
                _cvVolume = float.Parse(PlayerPrefs.GetString("CVVolume"));
            }
            else
            {
                PlayerPrefs.SetString("CVVolume", "0.7");
            }
        }

        /// <summary>
        /// 递归设置key，以便后续通过key找到AudioSource
        /// </summary>
        /// <param name="key"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        string SetAudioKey(string key,int i = 1)
        {
            return !_dicAudio.ContainsKey(key) ? key : SetAudioKey(key.Split('|')[0] + "|" + i.ToString(), i + 1);
        }

        /// <summary>
        /// 获得AudioSource
        /// </summary>
        /// <param name="key"></param>
        AudioSource GetAudioSource(string key)
        {
            var audioSource = GetAudioSourceRemove();
            if(audioSource == null)
            {
                audioSource = gameObject.AddComponent<AudioSource>();
            }
            _dicAudio.Add(SetAudioKey(key), audioSource);
            return audioSource;
        }

        /// <summary>
        /// 获得一个AudioSource并删除原来的item
        /// </summary>
        /// <param name="key"></param>
        AudioSource GetAudioSourceRemove()
        {
            string key = null;
            AudioSource value = null;
            foreach (var audioSource in _dicAudio.Where(audioSource => audioSource.Value != null && audioSource.Value.isPlaying == false))
            {
                key = audioSource.Key;
                value = audioSource.Value;
                break;
            }

            if (key == null) return null;
            _dicAudio.Remove(key);
            return value;
        }

        /// <summary>
        /// 载入一个音频
        /// </summary>
        /// 
        void LoadAudioClipAsync(string path, Action<AudioClip> fun)
        {
            //string[] names = path.Split('/');
            //string name = names[names.Length - 1];
            ResManager.LoadAudioPrefab(path, delegate (AudioClip obj)
            {
                fun?.Invoke(obj);
            });
        }
      
        /// <summary>
        /// 根据path停止播放(可以是某个路径的所有声音)
        /// </summary>
        public void StopByPath(string path)
        {
            foreach (var pair in _dicAudio.Where(pair => pair.Key.Contains(path)))
            {
                pair.Value.Stop();
            }
        }
        /// <summary>
        /// 播放声音，返回当前播放声音的持续时间/秒
        /// </summary>
        public float Play(string path,LuaFunction fuc)
        {
			if (!_enableSound) return 0;
            float sourceTime = 0;
            LoadAudioClipAsync(path, delegate (AudioClip ac)
            {
                if (ac == null) return;
                var source = GetAudioSource(path);
                if (source == null) return;
                source.clip = ac;
                source.loop = false;
                //_maxSoundVolume = ToolsCommons.GetSoundVolumeMax();
                source.volume = _soundVolume * _maxSoundVolume / 100;
                //Util.Log("SoundVolume:" + source.volume);
                source.Play();
                sourceTime = ac.length;
                if (fuc != null)
                    fuc.Call(sourceTime);
            });
            
            return sourceTime;
        }
        public void StopBG()
        {
            if (_bgAudio == null) return;
            _bgAudio.volume = _musicVolume;
            var fade = _bgAudio.DOFade(0, 0.5f);
            fade.SetEase(Ease.OutQuad);
            fade.onComplete = StopFadeOutFinish;
            _musicHistory = "";
        }

        public void EnabledBg(bool isEnabled)
        {
            if (_bgAudio != null)
            {
                _bgAudio.enabled = isEnabled;
            }
        }
		public void EnableSound(bool isEnabled)
		{
			_enableSound = isEnabled;
		}
		public bool GetEnableSound()
		{
			return _enableSound;
		}
        private void StopFadeOutFinish()
        {
            _bgAudio.Stop();
        }
        public void PlayBG(string path,bool isloop)
        {
            if (_musicHistory == path || _bgAudio == null) return;
            LoadAudioClipAsync(path, delegate (AudioClip ac)
            {
                if (ac == null) return;
                _musicHistory = path;
                if (_bgAudio.clip != null)
                {
                    //_maxMusicVolume = ToolsCommons.GetBGVolumeMax();
                    _bgAudio.volume = _musicVolume * _maxMusicVolume / 100;
                    //Util.Log("MusicVolume:" + BGAudio.volume);
                    var fade = _bgAudio.DOFade(0, 0.5f);
                    fade.SetEase(Ease.OutQuad);
                    fade.onComplete = () =>
                    {
                        FadeOutFinish(ac);
                        _bgAudio.loop = isloop;
                    };
                }
                else
                {
                    FadeOutFinish(ac);
                    _bgAudio.loop = isloop;
                }
            });
            
        }
        void FadeOutFinish(AudioClip clip)
        {
            // _bgAudio.clip = clip;
            // _bgAudio.loop = true;
            // _maxMusicVolume = ToolsCommons.GetBGVolumeMax();
            // _bgAudio.volume = _musicVolume * _maxMusicVolume / 100;
            // //Util.Log("MusicVolume:" + BGAudio.volume);
            // _bgAudio.Play();
            // var fade = _bgAudio.DOFade(_musicVolume, 0.8f);
            // fade.SetEase(Ease.OutQuad);
        }



        ///// <summary>
        ///// 播放CV声音，返回当前播放声音的持续时间/秒
        ///// </summary>
        //public float PlayCV(string path, LuaFunction fuc)
        //{
        //    float sourceTime = 0;
        //    LoadAudioClipAsync(path, delegate (AudioClip ac)
        //    {
        //        if (ac == null) return;
        //        var source = GetAudioSource(path);
        //        if (source == null) return;
        //        source.clip = ac;
        //        source.loop = false;
        //        //_maxCvVolume = ToolsCommons.GetCVVolumeMax();
        //        source.volume = _cvVolume * _maxCvVolume / 100;
        //        //Util.Log("CVVolume:" + source.volume);
        //        source.Stop();
        //        source.Play();
        //        sourceTime = ac.length;
        //        if (fuc != null)
        //            fuc.Call(sourceTime);
        //    });
        //    return sourceTime;
        //}

        ///// <summary>
        ///// 设置背景音乐音量
        ///// </summary>
        ///// <param name="volume"></param>
        //public void SetMusicVolume(float volume)
        //{
        //    _musicVolume = volume;
        //    _bgAudio.volume = _musicVolume;
        //    PlayerPrefs.SetString("MusicVolume", _musicVolume.ToString());
        //}

        ///// <summary>
        ///// 设置音效音量
        ///// </summary>
        ///// <param name="volume"></param>
        //public void SetSoundVolume(float volume)
        //{
        //    _soundVolume = volume;
        //    PlayerPrefs.SetString("SoundVolume", _soundVolume.ToString());
        //}

        ///// <summary>
        ///// 设置CV音量
        ///// </summary>
        ///// <param name="volume"></param>
        //public void SetCVVolume(float volume)
        //{
        //    _cvVolume = volume;
        //    PlayerPrefs.SetString("CVVolume", _cvVolume.ToString());
        //}

        /// <summary>
        /// 把录好的音段转化为base64的string。测试过不转base64直接用byte[]也是可以的
        /// </summary>
        public string AudioToByte(AudioSource audio)
        {
            var floatData = new float[audio.clip.samples * audio.clip.channels];
            audio.clip.GetData(floatData, 0);
            var outData = new byte[floatData.Length];
            Buffer.BlockCopy(floatData, 0, outData, 0, outData.Length);
            return Convert.ToBase64String(outData);
        }
        /// <summary>
        /// 把base64的string转化为audioSource
        /// </summary>
        public void ByteToAudio(string str, AudioSource audioSource)
        {
            var bytes = Convert.FromBase64String(str);
            var samples = new float[bytes.Length];
            Buffer.BlockCopy(bytes, 0, samples, 0, bytes.Length);
            audioSource.clip = AudioClip.Create("RecordClip", samples.Length, 1, 6000, false);
            audioSource.clip.SetData(samples, 0);
            audioSource.Play();
        }
    }
}